package Locomotive;

import java.awt.Color;
import java.awt.geom.Point2D;

/**
 *
 * @author Mikael Köhlmyr | mikael@kohlmyr.com | http://www.kmyr.net
 */
public class Particle implements Runnable {
    public static final int MAX_SIZE = 8;
    public static final int MIN_SIZE = 2;
    private Point2D.Double position;        // absolute center of Particle, not upper left corner
    private Point2D.Double velocity;
    private Thread active;
    private int radius;
    private Color color;
    
    private boolean escaping;
    private int timer;
   

    public Particle(){
        this.color = Util.get_random_color();
        this.radius = Util.get_random_buffered_integer(Particle.MAX_SIZE, Particle.MIN_SIZE);
        this.position = Util.get_random_buffered_point_in_bounds(Screen.WIDTH, Screen.HEIGHT, (this.radius*4));
        this.velocity = Util.get_random_pivoted_point(Physics.MAXIMUM_VELOCITY);
        this.escaping = false;
        this.timer = 0;
    }

    public void configure(){
        this.active = new Thread(this);
        // other things
        this.active.start();
    }

    public void run() {
        while(true){
            this.exist();
        }
    }

    public synchronized void exist(){
        this.handle_collisions();
        this.move();
        Particle.draw_to_buffer(this.get_drawfrom_x(), this.get_drawfrom_y(), this.color, this.radius);
        if(!this.escaping)
            this.timer++;
        try {
            this.wait();
        } catch (InterruptedException ex) {
            Util.print_exception(ex);
        }
    }

    public void move(){
        this.position.setLocation(this.position.x + this.velocity.x, this.position.y + ((!this.escaping) ? Physics.get_velocity_with_gravity(this.velocity.y, this.timer) : this.velocity.y));
    }

    public void handle_collisions(){
        System.out.println(this.timer);
        boolean esc = false;
        if(((this.position.x-this.radius) <= 0 || (this.position.x+this.radius) >= Screen.WIDTH) && !this.escaping){
            Physics.apply_bounce(this.velocity, Physics.BOUNCE_FLOOR, this.radius);
            this.velocity.x *= -1;
            esc = true;
        }
        if(((this.position.y-this.radius) <= 0 || (this.position.y+this.radius) >= Screen.HEIGHT) && !this.escaping){
            if((this.position.y+this.radius) >= Screen.HEIGHT){
                this.velocity.y = Physics.get_velocity_with_gravity(this.velocity.y, this.timer);
                Physics.apply_bounce(this.velocity, Physics.BOUNCE_FLOOR, this.radius);
                //Physics.apply_friction(this.velocity, Physics.FRICTION_WALL);
                this.timer = 0;
            }
            this.velocity.y *= -1;
            esc = true;
        }
        this.escaping = esc;
    }

    private static synchronized void draw_to_buffer(int x, int y, Color c, int radius){
        Screen.bufferg.setColor(c);
        Screen.bufferg.drawOval(x, y, radius*2, radius*2);
    }

    public synchronized void wake_up(){
        this.notify();
    }

    public synchronized void hibernate(){
        try {
            this.wait();
        } catch (InterruptedException ex) {
            Util.print_exception(ex);
        }
    }

    public double get_x(){
	return this.position.x;
    }

    public double get_y(){
	return this.position.y;
    }

    public int get_drawfrom_x(){
        return (int)(this.position.x - radius);
    }

    public int get_drawfrom_y(){
        return (int)(this.position.y - radius);
    }

    public double get_vel_x(){
        return this.velocity.x;
    }
    
    public double get_vel_y(){
        return this.velocity.y;
    }
}
